package com.softserveinc.lahire.gui;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;

import com.softserveinc.lahire.configurator.Configurator;

public class OptionsDialog extends JDialog {

	private static OptionsDialog instance;

	private JTabbedPane tabbedPane;
	private LinkedHashMap<String, JTable> tablesMap;
	private LinkedHashMap<String, Object> queueMap;
	
	// Create singleton instance of OptionsDialog

	public static synchronized OptionsDialog getInstance() {

		if (instance == null) {
			instance = new OptionsDialog();
		} else if (!instance.isVisible()) {
			instance.setVisible(true);
		}
		return instance;
	}

	private OptionsDialog() {

		// Set layout and other stuff
		customizeWindow();

		// Create tabbed & buttons panels
		
		tabbedPane = createTabbedPanel();
		JPanel buttonsPanel = createButtonsPanel();

		// Create ordered map of tables and their names, to store references to tables for further
		// use
		
		tablesMap = new LinkedHashMap<String, JTable>();

		// Create table tabs as much as configuration HashMap contains nested
		// HashMaps

		createTableTab(Configurator.getInstance().getHashMap(), ROOT_TAB_NAME);

		// Add both tabbed and buttons panels to the ContentPane 
		
		this.getContentPane().add(tabbedPane);
		this.getContentPane().add(buttonsPanel);


		// finally show dialog panel

		this.setVisible(true);

	}

	private void customizeWindow() {

		setTitle("Lahire options");
		setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		setSize(WINDOW_WIDTH, WINDOW_HEIGHT);

		// Set layout manager for ContentPane
		getContentPane().setLayout(new GridLayout(0, 1, 0, 0));

	}

	private JTabbedPane createTabbedPanel() {

		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		return tabbedPane;

	}

	private void createTableTab(HashMap<String, Object> map, String tabName) {

		queueMap = new LinkedHashMap<String, Object>();

		JTable table = createTable(map);
		JScrollPane scrollPanel = new JScrollPane(table);
		tabbedPane.addTab(tabName, null, scrollPanel, null);
		tablesMap.put(tabName, table);

		for (Map.Entry<String, Object> entry : queueMap.entrySet()) {

			createTableTab((HashMap<String, Object>) entry.getValue(),
					entry.getKey());

		}

	}

	private JTable createTable(HashMap<String, Object> map) {

		JTable jtbOptionsTable = new JTable(toTableModel(map)) {

			public boolean isCellEditable(int rowIndex, int colIndex) {
				if (this.getColumnName(colIndex).equals("Option")) {
					return false; // Disallow the editing of column 0
				}
				return true;
			}
		};

		return jtbOptionsTable;

	}

	private TableModel toTableModel(HashMap<String, Object> map) {
		DefaultTableModel model = new DefaultTableModel(new Object[] {
				"Option", "Value" }, 0);

		for (Map.Entry<String, Object> entry : map.entrySet()) {
			if (entry.getValue() instanceof HashMap<?, ?>) {

				queueMap.put(entry.getKey(), entry.getValue());

			} else {
				model.addRow(new Object[] { entry.getKey(), entry.getValue() });
			}
		}
		return model;
	}

	private JPanel createButtonsPanel() {

		JPanel jpButtonsPanel = new JPanel();
		jpButtonsPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));

		JButton jbtnOkButton = new JButton("Ok");
		jpButtonsPanel.add(jbtnOkButton);

		JButton jbtnCancelButton = new JButton("Cancel");
		jpButtonsPanel.add(jbtnCancelButton);

		jbtnCancelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				instance.dispose();
				instance=null;
			}
		});

		jbtnOkButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				Configurator.getInstance().setHashMap(returnConfig());
				System.out.println("Options saved");
				instance.dispose();
				instance=null;

			}
		});
		return jpButtonsPanel;
	}

	private HashMap<String, Object> returnConfig() {

		HashMap<String, Object> configMap = null;

		for (Map.Entry<String, JTable> entry : tablesMap.entrySet()) {

			HashMap<String, Object> map = toHashMap(entry.getValue());

			if (configMap != null) {

				configMap.put(entry.getKey(), map);
			} else {

				configMap = map;
			}
		}
		return configMap;
	}

	private HashMap<String, Object> toHashMap(JTable table) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		for (int i = 0; i < table.getModel().getRowCount(); i++) {
			map.put((String) table.getModel().getValueAt(i, 0), table
					.getModel().getValueAt(i, 1));
		}
		return map;
	}

	private static final String ROOT_TAB_NAME = "General";
	private static final int WINDOW_HEIGHT = 480;
	private static final int WINDOW_WIDTH = 640;

}
